import json
import re

from django import http
from django.contrib.auth import logout
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View
from django_redis import get_redis_connection

from apps.goods.models import SKU
from apps.users.models import User, Address
from apps.users.utils import generate_verify_email_url
from meiduo_mall.settings.dev import logger
from utils.response_code import RETCODE
from utils.secret import SecretOauth


class UserBrowserView(LoginRequiredMixin, View):
    # 保存用户的浏览记录
    def post(self, request):
        # 接收参数
        sku_id = json.loads(request.body.decode())['sku_id']
        # 校验
        try:
            sku = SKU.objects.get(id=sku_id)
        except:
            return http.HttpResponseForbidden('商品不存在')
        # 链接数据库
        client = get_redis_connection('history')
        redis_key = "history_%d" % request.user.id
        # 去重
        p1 = client.pipeline()
        p1.lrem(redis_key, 0, sku_id)
        p1.lpush(redis_key, sku_id)
        p1.ltrim(redis_key, 0, 4)
        # pass
        p1.execute()
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})

    def get(self, request):
        # 对浏览记录进行展示
        # 从redis链接
        client = get_redis_connection('history')
        sku_ids = client.lrange('history_%d' % request.user.id, 0, -1)
        skus_list = []
        for sku_id in sku_ids:
            sku = SKU.objects.get(id=sku_id)
            skus_list.append({
                'id': sku.id,
                'name': sku.name,
                'price': sku.price,
                'default_image_url': sku.default_image.url
            })
        # skus = SKU.objects.filter(id__in=sku_ids)
        # for sku in skus:
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'skus': skus_list})


class ChangePwdAddView(LoginRequiredMixin, View):
    def get(self, request):
        return render(request, 'user_center_pass.html')

    def post(self, request):
        # 1.接收参数
        old_password = request.POST.get('old_pwd')
        new_password = request.POST.get('new_pwd')
        new_password2 = request.POST.get('new_cpwd')
        # 2. 校验 判空, 判断正则
        user = request.user
        # 判断密码是否正确
        if not user.check_password(old_password):
            return render(request, 'user_center_pass.html', {'origin_pwd_errmsg': '原始密码错误'})
        # 3. 重新设置密码
        user.set_password(new_password)
        user.save()
        # 4.重定向登录页
        response = redirect(reverse('users:login'))
        # 5. 退出登录
        logout(request)
        # 6. 干掉cookie
        response.delete_cookie('username')
        return response


# 增加收货地址
class AddressAddView(LoginRequiredMixin, View):
    def post(self, request):
        # 限制增加个数 不能超过20个
        count = Address.objects.filter(user=request.user, is_deleted=False).count()
        # count = request.user.addresses.filter(is_deleted=False).count()
        if count > 20:
            return http.JsonResponse({'code': RETCODE.THROTTLINGERR, 'errmsg': '超过地址数量上限'})

        # 1.接收参数
        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')
        # 2.校验
        # 3.orm = create() save()
        address = Address.objects.create(
            user=request.user,
            title=receiver,
            receiver=receiver,
            province_id=province_id,
            city_id=city_id,
            district_id=district_id,
            place=place,
            mobile=mobile,
            tel=tel,
            email=email,
        )
        # 设置用户的默认地址
        if not request.user.default_address:
            request.user.default_address = address
            request.user.save()
        # 数据转换
        address_dict = {
            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }

        # 响应保存结果
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '新增地址成功', 'address': address_dict})


# 展示收货地址
class AddressView(LoginRequiredMixin, View):
    def get(self, request):
        addresses = Address.objects.filter(user=request.user, is_deleted=False)
        adressess_list = []
        for address in addresses:
            adressess_list.append({
                "id": address.id,
                "title": address.title,
                "receiver": address.receiver,
                "province": address.province.name,
                "city": address.city.name,
                "district": address.district.name,
                "place": address.place,
                "mobile": address.mobile,
                "tel": address.tel,
                "email": address.email
            })
        context = {
            'default_address_id': request.user.default_address_id,
            'addresses': adressess_list
        }
        return render(request, 'user_center_site.html', context)


# 激活邮箱
class EmailVerifyView(LoginRequiredMixin, View):
    def get(self, request):
        token = request.GET.get('token')
        data_dict = SecretOauth().loads(token)
        # 1.接收参数
        user_id = data_dict.get('user_id')
        email = data_dict.get('email')
        # 2.校验
        try:
            user = User.objects.get(id=user_id, email=email)
        except Exception as e:
            logger.error(e)
            return http.HttpResponseForbidden('token无效的')
        # 3.修改
        user.email_active = True
        user.save()
        # 4.返回
        return redirect(reverse('users:info'))
        # pass


# 添加邮箱
class EmailView(LoginRequiredMixin, View):
    def put(self, request):
        # 1.接收参数
        json_dict = json.loads(request.body.decode())
        email = json_dict.get('email')
        # 2.校验正则
        if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
            return http.HttpResponseForbidden('参数email有误')
        # 3.修改数据
        try:
            request.user.email = email
            request.user.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '添加邮箱失败'})
        # 发送邮件
        verify_url = generate_verify_email_url(request.user)

        from celery_tasks.email.tasks import send_verify_email
        send_verify_email.delay(email, verify_url)
        # 4.返回响应
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '添加邮箱成功'})
        # pass


# 用户中心
class UserInfoView(LoginRequiredMixin, View):
    def get(self, request):
        # 数据库查询数据
        user = request.user
        context = {
            'username': user.username,
            'mobile': user.mobile,
            'email': request.user.email,
            'email_active': request.user.email_active
        }
        # render的东西---jinja2渲染---let--vue渲染

        # 个人中心页面
        return render(request, 'user_center_info.html', context)
        # pass


# 推出功能
class LogOutView(View):
    def get(self, request):
        # 1.清除登录状态session
        from django.contrib.auth import logout
        logout(request)
        # 2.清除username     cookie
        response = redirect(reverse('contents:index'))
        response.delete_cookie('username')
        # 3.重定向到首页
        return response


# 4登录功能
class LoginView(View):
    def get(self, request):
        return render(request, 'login.html')

    def post(self, request):
        # 接受函数
        username = request.POST.get('username')
        password = request.POST.get('password')
        remembered = request.POST.get('remembered')
        from django.contrib.auth import authenticate, login
        user = authenticate(request, username=username, password=password)
        # 判断user是否存在
        if user is None:
            return render(request, 'login.html', {'account_errmsg': '用户名或者密码错误'})
        # 判断后保持登录状态
        login(request, user)

        # cookie对象
        next = request.GET.get('next')
        if next:
            response = redirect(next)
        else:
            response = redirect(reverse('contents:index'))
        # 判断是否记住登录
        if remembered != 'on':
            # 多选按钮的选中会返回on来表达,返回on代表记住,返回的不为on代表没有选中记住按钮
            # 0表示绘画结束就失效了
            request.session.set_expiry(0)
        else:
            # none代表采取默认值即两个星期
            request.session.set_expiry(None)
            # 把用户名存在cookie里面返回
            response.set_cookie('username', user.username, max_age=2 * 14 * 24 * 3600)
            # 跳转到首页
        return response


# 判断手机号是否重复
class MobileCountView(View):
    def get(self, request, mobile):
        count = User.objects.filter(mobile=mobile).count()
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'count': count})


class UsernameCountView(View):
    """判断用户名是否重复注册"""

    def get(self, request, username):
        """
        :param request: 请求对象
        :param username: 用户名
        :return: JSON
        """
        count = User.objects.filter(username=username).count()
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'count': count})


class RegisterView(View):
    """
     注册视图
    """

    def get(self, request):
        return render(request, 'register.html')

    def post(self, requset):
        username = requset.POST.get('username')
        password = requset.POST.get('password')
        password2 = requset.POST.get('password2')
        mobile = requset.POST.get('mobile')
        allow = requset.POST.get('allow')

        if not all([username, password, password2, mobile, allow]):
            return http.HttpResponseForbidden('缺少参数')
        if not re.match('^[a-zA-Z0-9_-]{5,20}$', username):
            return http.HttpResponseForbidden('请输入5-20个字符的用户')
        if not re.match('^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseForbidden('请输入8-20个数字字母的密码')
        if password != password2:
            return http.HttpResponseForbidden('两次输入的密码不一致')
        if not re.match('^1[345789]\d{9}$', mobile):
            return http.HttpResponseForbidden('手机号格式有误')
        if allow != 'on':
            return http.HttpResponseForbidden('请阅读后勾选同意')
        # 判断短信验证码是否正确
        sms_code = requset.POST.get('msg_code')
        redis_sms_client = get_redis_connection('sms_code')
        redis_sms_code = redis_sms_client.get('sms_%s' % mobile)
        print(redis_sms_code)
        if not redis_sms_code:
            return render(requset, 'register.html', {'sms_code_errmsg': '无效的短信验证码'})
        redis_sms_client.delete('sms_%s' % mobile)
        if sms_code != redis_sms_code.decode():
            return render(requset, 'register.html', {'sms_code_errmsg': '短信验证码不正确'})

        user = User.objects.create_user(username=username, password=password, mobile=mobile)
        from django.contrib.auth import login
        login(requset, user)

        # return redirect('/')
        return redirect(reverse('contents:index'))
